import pandas as pd  # 导入pandas库，用于数据处理
import numpy as np  # 导入numpy库，用于数值计算

# 读取预处理好的文档主题数据
doc_topic_df = pd.read_csv('tfidf_nmf_8topics.csv')

# 定义主题名称列表（需与CSV文件中的列名一致）
topic_names = ['Tech', 'Modeling', 'Chatbots', 'Deep Learning', 'Coding', 'Business', 'Careers', 'NLP']

# 提取主题向量矩阵（形状：文档数×主题数）
topic_array = np.array(doc_topic_df[topic_names])

# 计算所有文档向量的L2范数（模长）
norms = np.linalg.norm(topic_array, axis=1)

# 打印矩阵形状（验证数据维度）
print(f"文档数×主题数: {topic_array.shape}")


def compute_dists(top_vec, topic_array):
    """
    计算余弦相似度的核心函数

    参数：
    top_vec - 用户输入的主题向量（1×8）
    topic_array - 所有文档的主题向量矩阵（n×8）

    返回：
    余弦相似度数组（n×1）
    """
    # 计算点积（n×1）
    dots = np.matmul(topic_array, top_vec)

    # 计算输入向量的模长
    input_norm = np.linalg.norm(top_vec)

    # 计算余弦相似度（避免除零错误）
    co_dists = dots / (input_norm * norms + 1e-8)

    return co_dists


def produce_rec(top_vec, topic_array, doc_topic_df, rand=15):
    """
    生成推荐结果的函数

    参数：
    top_vec - 用户输入的主题向量（1×8）
    topic_array - 所有文档的主题向量矩阵（n×8）
    doc_topic_df - 原始文档数据
    rand - 随机扰动强度（控制推荐多样性）

    返回：
    推荐的文档记录
    """
    # 对输入向量添加随机扰动（增加推荐多样性）
    top_vec = top_vec + np.random.rand(8) / (np.linalg.norm(top_vec)) * rand

    # 计算余弦相似度
    co_dists = compute_dists(top_vec, topic_array)

    # 找到相似度最高的文档索引
    best_idx = np.argmax(co_dists)

    # 返回推荐的文档记录
    return doc_topic_df.loc[best_idx]


# 测试推荐系统
if __name__ == "__main__":
    # 定义用户兴趣向量（8个主题权重）
    tech = 0
    modeling = 0
    chatbots = 0
    deep = 5  # 深度学习主题权重较高
    coding = 0
    business = 0
    careers = 0
    nlp = 5  # NLP主题权重较高

    # 组合成用户兴趣向量
    top_vec = np.array([tech, modeling, chatbots, deep, coding, business, careers, nlp])

    # 生成推荐结果
    rec = produce_rec(top_vec, topic_array, doc_topic_df)

    # 打印推荐结果
    print("推荐文章信息：")
    print(rec[['title', 'allTags', 'readingTime']])  # 打印标题、标签和阅读时间